//------------------------------------------------------------------------------
// I2CHardwareTypes.cs
//
//------------------------------------------------------------------------------
using Microsoft.Ccr.Core;
using Microsoft.Dss.ServiceModel.Dssp;
using Microsoft.Dss.Core.Attributes;
using System;
using System.Collections.Generic;

using W3C.Soap;
using generici2c = Generic.Protocols.I2C.Proxy;
using System.IO.Ports;
using Microsoft.Dss.Core.DsspHttp;
using System.ComponentModel;

namespace Devantech.Services.I2C.Hardware
{

    #region Contract
    /// <summary>
    /// I2CHardware Contract Class
    /// </summary>
    public sealed class Contract
    {
        /// I2CHardware contract identifier
        [DataMember, Description("")]
        public const string Identifier = "http://www.robot-electronics.co.uk/2006/10/i2chardware.html";
        
    }
    #endregion

    #region Operations
    /// <summary>
    /// 
    /// </summary>
    public class I2CHardwareOperations : PortSet<DsspDefaultLookup,
        DsspDefaultDrop,
        Get,
        Replace,
        DevantechReadData,
        HttpGet,
        HttpPost>
    {
    }
    #endregion

    #region Standard Messages
    /// <summary>
    /// 
    /// </summary>
    public class Get : Get<GetRequestType, PortSet<StateType, Fault>>
    {
    }

    /// <summary>
    /// 
    /// </summary>
    public class Replace : Replace<StateType, PortSet<DefaultReplaceResponseType, Fault>>
    {
    }
    #endregion

    #region Devantech I2C Specific Requests
    /// <summary>
    /// Used to support CM02 internal messages
    /// </summary>
    public class DevantechReadData : Update<DevantechReadDataRequest, PortSet<generici2c.ReturnData, Fault>>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DevantechReadData"/> class.
        /// </summary>
        public DevantechReadData()
            : base(new DevantechReadDataRequest())
        {
        }
    }

    /// <summary>
    /// Used to support Devantech internal messages
    /// </summary>
    [DataContract]
    public class DevantechReadDataRequest
    {
        private byte _command;
        private byte[] _data;
        private int _numBytes;

        /// <summary>
        /// Gets or sets the command.
        /// </summary>
        /// <value>The command.</value>
        [DataMember, Description("")]
        public byte Command
        {
            get { return this._command; }
            set { this._command = value; }
        }

        /// <summary>
        /// Gets or sets the data.
        /// </summary>
        /// <value>The data.</value>
        [DataMember, Description("")]
        public byte[] Data
        {
            get { return this._data; }
            set { this._data = value; }
        }

        /// <summary>
        /// Gets or sets the num bytes.
        /// </summary>
        /// <value>The num bytes.</value>
        [DataMember, Description("")]
        public int NumBytes
        {
            get { return this._numBytes; }
            set { this._numBytes = value; }
        }
    }
    #endregion

    #region State
    /// <summary>
    /// 
    /// </summary>
    [DataContract]
    public class StateType
    {
        private string _comPort = "COM3";
        private DateTime _lastContact;
        private bool _initialised = false;
        private int _portSpeed = 19200;
        private Parity _parity = Parity.None;
        private int _dataBits = 8;
        private StopBits _stopBits = StopBits.One; // one is correct for the RF04, but the USB I2C needs two
        private List<Module> _recentModules;
        private List<ModuleType> _moduleTypes;
        private bool _enableHealthMonitoring;
        private bool _startHardwareServices;
        private bool _isScanning = false;

        /// <summary>
        /// Gets or sets the COM port.
        /// </summary>
        /// <value>The COM port.</value>
        [DataMember, Description("")]
        public string ComPort
        {
            get { return this._comPort; }
            set { this._comPort = value; }
        }

        /// <summary>
        /// Gets or sets the port speed.
        /// </summary>
        /// <value>The port speed.</value>
        [DataMember, Description("")]
        public int PortSpeed
        {
            get { return this._portSpeed; }
            set { this._portSpeed = value; }
        }

        /// <summary>
        /// Gets or sets the parity value.
        /// </summary>
        /// <value>The parity value.</value>
        [DataMember, Description("")]
        public Parity ParityValue
        {
            get { return this._parity; }
            set { this._parity = value; }
        }

        /// <summary>
        /// Gets or sets the data bits.
        /// </summary>
        /// <value>The data bits.</value>
        [DataMember, Description("")]
        public int DataBits
        {
            get { return this._dataBits; }
            set { this._dataBits = value; }
        }

        /// <summary>
        /// Gets or sets the stop bits value.
        /// </summary>
        /// <value>The stop bits value.</value>
        [DataMember, Description("")]
        public StopBits StopBitsValue
        {
            get { return this._stopBits; }
            set { this._stopBits = value; }
        }

        /// <summary>
        /// Gets or sets the last contact.
        /// </summary>
        /// <value>The last contact.</value>
        [DataMember, Description("")]
        public DateTime LastContact
        {
            get { return this._lastContact; }
            set { this._lastContact = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="StateType"/> is initialised.
        /// </summary>
        /// <value><c>true</c> if initialised; otherwise, <c>false</c>.</value>
        [DataMember, Description("")]
        public bool Initialised
        {
            get { return this._initialised; }
            set { this._initialised = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is scanning.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is scanning; otherwise, <c>false</c>.
        /// </value>
        [DataMember, Description("")]
        public bool IsScanning
        {
            get { return this._isScanning; }
            set { this._isScanning = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [enable health monitoring].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [enable health monitoring]; otherwise, <c>false</c>.
        /// </value>
        [DataMember, Description("")]
        public bool EnableHealthMonitoring
        {
            get { return this._enableHealthMonitoring; }
            set { this._enableHealthMonitoring = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [start hardware services].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [start hardware services]; otherwise, <c>false</c>.
        /// </value>
        [DataMember, Description("")]
        public bool StartHardwareServices
        {
            get { return this._startHardwareServices; }
            set { this._startHardwareServices = value; }
        }

        /// <summary>
        /// Gets or sets the recent modules.
        /// </summary>
        /// <value>The recent modules.</value>
        [DataMember, Description("")]
        public List<Module> RecentModules
        {
            get { return _recentModules; }
            set { this._recentModules = value; }
        }


        /// <summary>
        /// Gets or sets the module types.
        /// </summary>
        /// <value>The module types.</value>
        [DataMember, Description("")]
        public List<ModuleType> ModuleTypes
        {
            get { return _moduleTypes; }
            set { this._moduleTypes = value; }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [DataContract]
    public class Module
    {
        private string _name;
        private string _moduleTypeName;
        private string _moduleContract;
        private byte _i2cAddress;
        private DateTime _timestamp;
        private long _writeCount;
        private long _readCount;
        private long _errorCount;
        private string _activeService;

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        [DataMember, Description("")]
        public string Name
        {
            get { return _name; }
            set { this._name = value; }
        }

        /// <summary>
        /// Gets or sets the name of the module type.
        /// </summary>
        /// <value>The name of the module type.</value>
        [DataMember, Description("")]
        public string ModuleTypeName
        {
            get { return _moduleTypeName; }
            set { this._moduleTypeName = value; }
        }

        /// <summary>
        /// Gets or sets the module contract.
        /// </summary>
        /// <value>The module contract.</value>
        [DataMember, Description("")]
        public string ModuleContract
        {
            get { return _moduleContract; }
            set { this._moduleContract = value; }
        }

        /// <summary>
        /// Gets or sets the i2 C address.
        /// </summary>
        /// <value>The i2 C address.</value>
        [DataMember, Description("")]
        public byte I2CAddress
        {
            get { return _i2cAddress; }
            set { this._i2cAddress = value; }
        }

        /// <summary>
        /// Gets or sets the timestamp.
        /// </summary>
        /// <value>The timestamp.</value>
        [DataMember, Description("")]
        public DateTime Timestamp
        {
            get { return _timestamp; }
            set { this._timestamp = value; }
        }

        /// <summary>
        /// Gets or sets the active service.
        /// </summary>
        /// <value>The active service.</value>
        [DataMember, Description("")]
        public string ActiveService
        {
            get { return _activeService; }
            set { this._activeService = value; }
        }

        /// <summary>
        /// Gets or sets the write count.
        /// </summary>
        /// <value>The write count.</value>
        [DataMember, Description("")]
        public long WriteCount
        {
            get { return _writeCount; }
            set { this._writeCount = value; }
        }

        /// <summary>
        /// Gets or sets the read count.
        /// </summary>
        /// <value>The read count.</value>
        [DataMember, Description("")]
        public long ReadCount
        {
            get { return _readCount; }
            set { this._readCount = value; }
        }

        /// <summary>
        /// Gets or sets the error count.
        /// </summary>
        /// <value>The error count.</value>
        [DataMember, Description("")]
        public long ErrorCount
        {
            get { return _errorCount; }
            set { this._errorCount = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Module"/> class.
        /// </summary>
        public Module() { }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="Module"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="typeName">Name of the type.</param>
        /// <param name="i2cAddress">The i2c address.</param>
        /// <param name="contract">The contract.</param>
        public Module(string name, string typeName, byte i2cAddress, string contract) {
            Name = name;
            ModuleTypeName = typeName;
            I2CAddress = i2cAddress;
            ModuleContract = contract;
            Timestamp = DateTime.Now;
            ActiveService = "";
            WriteCount = 0;
            ReadCount = 0;
            ErrorCount = 0;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    [DataContract]
    public class ModuleType
    {
        private string _name;
        private string _type;
        private byte[] _possibleI2CAddresses;
        private string _moduleContract;
        private List<Test> _tests;

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        [DataMember, Description("")]
        public string Name
        {
            get { return _name; }
            set { this._name = value; }
        }

        /// <summary>
        /// Gets or sets the type.
        /// </summary>
        /// <value>The type.</value>
        [DataMember, Description("")]
        public string Type
        {
            get { return _type; }
            set { this._type = value; }
        }

        /// <summary>
        /// Gets or sets the possible i2 C addresses.
        /// </summary>
        /// <value>The possible i2 C addresses.</value>
        [DataMember, Description("")]
        public byte[] PossibleI2CAddresses
        {
            get { return _possibleI2CAddresses; }
            set { this._possibleI2CAddresses = value; }
        }

        /// <summary>
        /// Gets or sets the module contract.
        /// </summary>
        /// <value>The module contract.</value>
        [DataMember, Description("")]
        public string ModuleContract
        {
            get { return _moduleContract; }
            set { this._moduleContract = value; }
        }

        /// <summary>
        /// Gets or sets the tests.
        /// </summary>
        /// <value>The tests.</value>
        [DataMember, Description("")]
        public List<Test> Tests
        {
            get { return _tests; }
            set { this._tests = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ModuleType"/> class.
        /// </summary>
        public ModuleType()
        {
            //_possibleI2CAddresses = new List<byte>();
            _tests = new List<Test>();
        }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="ModuleType"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="type">The type.</param>
        /// <param name="i2cAddresses">The i2c addresses.</param>
        /// <param name="contract">The contract.</param>
        /// <param name="tests">The tests.</param>
        public ModuleType(string name, string type, byte[] i2cAddresses, string contract, List<Test> tests)
        {
            this._name = name;
            this._type = type;
            this._possibleI2CAddresses = i2cAddresses;
            this._moduleContract = contract;
            this._tests = tests;
        }
    }

    /// <summary>
    /// Used to disambiguate sensors
    /// </summary>
    [DataContract]
    public class Test
    {
        private byte _registerAddress;
        private byte _minValue;
        private byte _maxValue;

        /// <summary>
        /// Gets or sets the register address.
        /// </summary>
        /// <value>The register address.</value>
        [DataMember, Description("")]
        public byte RegisterAddress
        {
            get { return _registerAddress; }
            set { this._registerAddress = value; }
        }

        /// <summary>
        /// Gets or sets the min value.
        /// </summary>
        /// <value>The min value.</value>
        [DataMember, Description("")]
        public byte MinValue
        {
            get { return _minValue; }
            set { this._minValue = value; }
        }

        /// <summary>
        /// Gets or sets the max value.
        /// </summary>
        /// <value>The max value.</value>
        [DataMember, Description("")]
        public byte MaxValue
        {
            get { return _maxValue; }
            set { this._maxValue = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Test"/> class.
        /// </summary>
        public Test() { }

        /// <summary>
        /// Initializes a new instance of the <see cref="Test"/> class.
        /// </summary>
        /// <param name="register">The register.</param>
        /// <param name="min">The min.</param>
        /// <param name="max">The max.</param>
        public Test(byte register, byte min, byte max)
        {
            this._registerAddress = register;
            this._minValue = min;
            this._maxValue = max;
        }
    }

    #endregion
}
